`timescale 1ns / 1ps
module NC_TOP (
    
);

reg clk_in;
wire rw_clk, ecc_clk, clko;
reg rst_n;
initial begin
    clk_in = 1;
    forever #1 clk_in = ~clk_in;
end

initial begin
    rst_n = 1;
    #100 rst_n = 0;
    #20  rst_n = 1;
end


clock_divider u_clock_divider(
	.clk   (clk_in   ),
    .rst_n (rst_n ),
    .div1  (20  ),
    .clk1  (clko  ),
    .div2  (10  ),
    .clk2  (rw_clk  ),
    .div3  (25  ),
    .clk3  (ecc_clk  )
);

wire code_success_w;
wire decode_success_w;

reg[31:0] wdata_r;
wire[31:0] rdata_w;
reg       wvalid_r;
wire       rvalid_w;
wire      w_en_w;
reg       r_en_r;

reg[2:0]  cmd_r;
reg[3:0]  cmd_counter_r;
wire      cmd_finish_w;
reg[39:0] address_r;



wire        we_s_w;
wire        re_s_w;
wire        cle_w;
wire        ale_w;
wire[7:0]   dq_i_w;
wire[7:0]   dq_o_w;
wire        dq_oen_w;
wire        dqs_i_w;
wire        dqs_o_w;
wire        dqs_oen_w;
wire        rb_s_w;

wire[7:0] dq_w;
assign dq_i_w = dq_w;
assign dq_w = dq_oen_w ? dq_o_w : 8'hzz;

wire dqs_w;
wire dqs_dly;
assign dqs_i_w = dqs_dly;
assign dqs_w = dqs_oen_w ? dqs_o_w : 1'bz;
wire can_read;
DLL_design u_DLL_design(
	.clk    (clk_in     ),
    .rst_n  (rst_n      ),
    .fin    (dqs_w      ),
    .fout   (dqs_dly    ),
    .locked (locked     ),
    .fin_en (1          ),
    .dly    (7          )
);

NANDFlash_Control u_NANDFlash_Control(
	.clk            (clko            ),
    .rst_n          (rst_n          ),
    .ECCclk         (ecc_clk         ),
    .decode_en      (1               ),
    .code_en        (1               ),
    .code_success   (code_success   ),
    .decode_success (decode_success ),
    .page_size      (16'd1024       ),
    .ecc_size       (16'd128         ),
    .block_address_num(3             ),
    .page_address_num(2              ),

    .w_data         (wdata_r         ),
    .w_valid        (wvalid_r        ),
    .w_en           (w_en_w           ),
    .r_data         (rdata_w         ),
    .r_valid        (rvalid_w        ),
    .r_en           (r_en_r           ),
    .wr_clk         (rw_clk         ),
    .r_can_read     (can_read),

    .cmd            (cmd_r            ),
    .cmd_counter    (cmd_counter_r    ),
    .cmd_finish     (cmd_finish_w     ),
    .address        (address_r        ),

    .F_WE           (we_s_w         ),
    .F_RE           (re_s_w         ),
    .F_CLE          (cle_w          ),
    .F_ALE          (ale_w          ),
    .F_DQ_i         (dq_i_w         ),
    .F_DQ_o         (dq_o_w         ),
    .F_DQ_oen       (dq_oen_w       ),
    .F_DQS_i        (dqs_i_w        ),
    .F_DQS_o        (dqs_o_w        ),
    .F_DQS_oen      (dqs_oen_w      ),
    .F_RB           (rb_s_w         )
);

nand_model u_nand_model(
    .Dq_Io     (dq_w     ),
    .Dqs       (dqs_w    ),
    .Cle       (cle_w    ),
    .Ale       (ale_w    ),
    .Ce_n      (0        ),
    .Clk_We_n  (we_s_w   ),
    .Wr_Re_n   (re_s_w   ),
    .Wp_n      (1        ),
    .Rb_n      (rb_s_w   ),
    .ENi       (1        ),
    .ENo       (         ),
    .Dqs_c     (         ),
    .Re_c      (1'b1     )
);

always @(negedge clko or negedge rst_n) begin
    if (!rst_n) begin
        cmd_counter_r <= 1;
        cmd_r <= 0;
        wvalid_r <= 0;
        address_r <= 0;
    end else begin
        if (cmd_finish_w == 1) begin
            case (cmd_r)
                3'b000 : begin
                    cmd_r <= 3'b111; 
                    cmd_counter_r <= cmd_counter_r + 1;
                end 
                3'b111 :begin
                    cmd_r <= 3'b110;
                    cmd_counter_r <= cmd_counter_r + 1;
                end 
                3'b110 :begin
                    cmd_r <= 3'b010;
                    cmd_counter_r <= cmd_counter_r + 1;
                end
                3'b010 :begin
                    cmd_r <= 3'b001;
                    cmd_counter_r <= cmd_counter_r + 1;
                end  
                default: cmd_r <= cmd_r;
            endcase
        end else begin

        end
    end
end

always @(posedge clko or negedge rst_n) begin
    if (!rst_n) begin
        address_r <= 0;
    end else begin
        case (cmd_r)
           3'b110 : address_r <= {32'b0, 8'h01};
           3'b010 : address_r <= 40'h0040_0000_00;
           3'b001 : address_r <= 40'h0040_0000_00;
            default: address_r <= 0;
        endcase
    end
end

reg[7:0] data1;
reg[7:0] data2;
reg[7:0] data3;
reg[7:0] data4;
always @(posedge rw_clk or negedge rst_n) begin
    if (!rst_n) begin
        data1 <= 0;
        data2 <= 1;
        data3 <= 2;
        data4 <= 3;
        wdata_r <= 0;
        wvalid_r <= 0;
        r_en_r <= 0;
    end else begin
        if (w_en_w) begin
            if(cmd_r == 3'b110) begin
                wdata_r <= {24'h0, 8'b0000_0000};
                wvalid_r <= 1;
            end else if (cmd_r == 3'b010) begin
                wvalid_r <= 1;
                wdata_r <= {data1,data2, data3, data4};
                data1 <= data1 + 4;
                data2 <= data2 + 4;
                data3 <= data3 + 4;
                data4 <= data4 + 4;
            end else begin
                r_en_r <= 1;
            end
        end else begin
            wvalid_r <= 0;   
            if (cmd_r == 3'b001) begin
                if (can_read) begin
                    r_en_r <= 1;
                end else begin
                    r_en_r <= 0;
                end
            end else begin
                r_en_r <= 0;
            end 
        end
    end
end


endmodule